Dockerコンテナ内のディレクトリ構成を確認してみる

Dockerコンテナ内のディレクトリ構成を確認してみる

Dockerコンテナ内のディレクトリ構成を簡単なnode.jsのアプリケーションを作成して確認してみます。
Clock Icon2024.10.29

SBJソリューション部のserinaです。

先日、Dockerを用いた作業をしていてうまくいかないことがあり、立ち上がったコンテナの中身についてあまり理解してないなぁ、と感じたことがありました。

なので、今回は、Dockerコンテナのディレクトリ構成を確認してみます。

node.jsのアプリケーションを作成して確認してみる

ブラウザで Hello World! を表示する簡単なnode.jsのアプリケーションを作成して、ディレクトリ構成を確認していきます。

ディレクトリ構成

~/tmp/myapp 19s
❯ tree .
.
├── Dockerfile
├── app.js
└── package.json

前準備: ファイル作成

Dockerfile

# ベースイメージを指定
FROM node:alpine

# 作業ディレクトリを設定
WORKDIR /app

# package.jsonとpackage-lock.jsonをコピー
COPY package*.json ./

# 依存関係をインストール
RUN npm install

# アプリケーションのソースコードをコピー
COPY . .

# アプリケーションを起動
CMD ["node", "app.js"]

app.js

// app.js
const http = require('http');

const hostname = '0.0.0.0';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

package.json

{
  "name": "myapp",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "http": "0.0.0"
  }
}

確認作業

Dockerをビルドします。

~/tmp/myapp 11s
❯ docker build -t myapp .
[+] Building 3.5s (10/10) FINISHED                                                  docker:rancher-desktop
 => [internal] load build definition from Dockerfile                                                  0.0s
 => => transferring dockerfile: 393B                                                                  0.0s
 => [internal] load metadata for docker.io/library/node:alpine                                        0.0s
 => [internal] load .dockerignore                                                                     0.0s
 => => transferring context: 2B                                                                       0.0s
 => [1/5] FROM docker.io/library/node:alpine                                                          0.0s
 => [internal] load build context                                                                     0.0s
 => => transferring context: 980B                                                                     0.0s
 => [2/5] WORKDIR /app                                                                                0.0s
 => [3/5] COPY package*.json ./                                                                       0.0s
 => [4/5] RUN npm install                                                                             3.4s
 => [5/5] COPY . .                                                                                    0.0s
 => exporting to image                                                                                0.0s
 => => exporting layers                                                                               0.0s
 => => writing image sha256:34aec6d03e817ca9a7a3037683d519482717db47e9fec671f6103d1aa99ca05c          0.0s 
 => => naming to docker.io/library/myapp  

tree構造で確かめたいので、docker runでコンテナのシェルに入ったら tree コマンドを入れます。

docker run -it myapp /bin/sh 
/app # apk add --no-cache tree
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/aarch64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/aarch64/APKINDEX.tar.gz
(1/1) Installing tree (2.1.1-r0)
Executing busybox-1.36.1-r29.trigger
OK: 12 MiB in 17 packages

全部表示すると大量に出てきてしまうので、1階層のディレクトリを確認してみます。

/app # tree -d -L 1 /
/
├── app
├── bin
├── dev
├── etc
├── home
├── lib
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin
├── srv
├── sys
├── tmp
├── usr
└── var

19 directories

Dockerコンテナ内ではLinuxベースのファイルシステムが使われています。
なので、それと似たようなディレクトリ構成になっています。

WORKDIR /app したので、 /app が作られていることが確認できます。
このディレクトリ配下を確認すると、ファイルがあることが確認できます。

/app # cd /app
/app # tree .
.
├── Dockerfile
├── app.js
├── node_modules
├── package-lock.json
└── package.json

グローバルインストールした場合の node_modules を確認してみる

先日、この問題で悩んだことがあり、package.jsonを作成しなかった場合は NODE_PATH を通す場所があることがわかりました。
調べた結果、/usr/local/libnode_modulesが作られることがわかっているので、そのことを確認していきます。

前準備: ファイルを変更

package.json を削除します。

変更後のDockerfile

# ベースイメージを指定
FROM node:alpine

# 作業ディレクトリを設定
WORKDIR /app

# 環境変数を設定 <- 🌟追加
ENV NODE_PATH=/usr/local/lib/node_modules

# 必要なモジュールをグローバルにインストール <- 🌟変更
RUN npm install -g http

# アプリケーションのソースコードをコピー
COPY . .

# アプリケーションを起動
CMD ["node", "app.js"]

変更後のディレクトリ構成

~/tmp/myapp 57s
❯ tree .
.
├── Dockerfile
└── app.js

1 directory, 2 files

確認作業

再度、ビルドします。

docker build -t myapp .
[+] Building 1.2s (9/9) FINISHED                                                    docker:rancher-desktop
 => [internal] load build definition from Dockerfile                                                  0.0s
 => => transferring dockerfile: 428B                                                                  0.0s
 => [internal] load metadata for docker.io/library/node:alpine                                        0.0s
 => [internal] load .dockerignore                                                                     0.0s
 => => transferring context: 2B                                                                       0.0s
 => [1/4] FROM docker.io/library/node:alpine                                                          0.0s
 => [internal] load build context                                                                     0.0s
 => => transferring context: 454B                                                                     0.0s
 => CACHED [2/4] WORKDIR /app                                                                         0.0s
 => [3/4] RUN npm install -g http                                                                     1.1s
 => [4/4] COPY . .                                                                                    0.0s
 => exporting to image                                                                                0.0s
 => => exporting layers                                                                               0.0s
 => => writing image sha256:052f11f8a331fc31cdb444f8772f29523941f18ba12a610358c816ae1cf4a5f3          0.0s
 => => naming to docker.io/library/myapp

treeコマンドをインストールします。

docker run -it myapp /bin/sh
/app # apk add --no-cache tree
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/aarch64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/aarch64/APKINDEX.tar.gz
(1/1) Installing tree (2.1.1-r0)
Executing busybox-1.36.1-r29.trigger
OK: 12 MiB in 17 packages

2階層までの usr/local を確認します。

/ # tree -a -L 2 /usr/local
/usr/local
├── bin
│   ├── corepack -> ../lib/node_modules/corepack/dist/corepack.js
│   ├── docker-entrypoint.sh
│   ├── node
│   ├── npm -> ../lib/node_modules/npm/bin/npm-cli.js
│   ├── npx -> ../lib/node_modules/npm/bin/npx-cli.js
│   ├── yarn -> /opt/yarn-v1.22.22/bin/yarn
│   └── yarnpkg -> /opt/yarn-v1.22.22/bin/yarnpkg
├── include
│   └── node
├── lib
│   └── node_modules
└── share
    ├── doc
    └── man

lib/node_modules を見つけられました。

最後に

Dockerをふわっとした理解で使っていたので、もやもやがスッキリしました!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.